#include <riscv/asm.h>
#include <riscv/asm-offset.h>
#include <asm/linkage.h>

/*
 * Integer register context switch
 * The callee-saved registers must be saved and restored.
 *
 *   a0: previous task_struct (must be preserved across the switch)
 *   a1: next task_struct
 *   a2: prev thread_info
 *   a3: next thread_info
 *   a4: offset
 *
 * The value of a0 and a1 must be preserved by this function, as that's how
 * arguments are passed to schedule_tail.
 */
ENTRY(__switch_to)
    add a2, a2, a4
	add a3, a3, a4
    /* Save context into prev->thread */
	REG_S ra,  TASK_THREAD_RA_RA(a2)
	REG_S sp,  TASK_THREAD_SP_RA(a2)
	REG_S s0,  TASK_THREAD_S0_RA(a2)
	REG_S s1,  TASK_THREAD_S1_RA(a2)
	REG_S s2,  TASK_THREAD_S2_RA(a2)
	REG_S s3,  TASK_THREAD_S3_RA(a2)
	REG_S s4,  TASK_THREAD_S4_RA(a2)
	REG_S s5,  TASK_THREAD_S5_RA(a2)
	REG_S s6,  TASK_THREAD_S6_RA(a2)
	REG_S s7,  TASK_THREAD_S7_RA(a2)
	REG_S s8,  TASK_THREAD_S8_RA(a2)
	REG_S s9,  TASK_THREAD_S9_RA(a2)
	REG_S s10, TASK_THREAD_S10_RA(a2)
	REG_S s11, TASK_THREAD_S11_RA(a2)

	/* Restore context from next->thread */
	REG_L ra,  TASK_THREAD_RA_RA(a3)
	REG_L sp,  TASK_THREAD_SP_RA(a3)
	REG_L s0,  TASK_THREAD_S0_RA(a3)
	REG_L s1,  TASK_THREAD_S1_RA(a3)
	REG_L s2,  TASK_THREAD_S2_RA(a3)
	REG_L s3,  TASK_THREAD_S3_RA(a3)
	REG_L s4,  TASK_THREAD_S4_RA(a3)
	REG_L s5,  TASK_THREAD_S5_RA(a3)
	REG_L s6,  TASK_THREAD_S6_RA(a3)
	REG_L s7,  TASK_THREAD_S7_RA(a3)
	REG_L s8,  TASK_THREAD_S8_RA(a3)
	REG_L s9,  TASK_THREAD_S9_RA(a3)
	REG_L s10, TASK_THREAD_S10_RA(a3)
	REG_L s11, TASK_THREAD_S11_RA(a3)

    move tp, a1
    ret
